package cc.shacocloud.mirage.utils.converter.support;

import cc.shacocloud.mirage.utils.ClassUtil;
import cc.shacocloud.mirage.utils.converter.ConversionSupport;
import cc.shacocloud.mirage.utils.converter.TypeDescriptor;
import cc.shacocloud.mirage.utils.date.DateUtil;
import cc.shacocloud.mirage.utils.date.TemporalUtil;
import org.jetbrains.annotations.NotNull;

import java.sql.Time;
import java.sql.Timestamp;
import java.time.temporal.TemporalAccessor;
import java.util.Calendar;
import java.util.Date;

/**
 * 转换为 {@link Date} 类型的转换器
 *
 * @author 思追(shaco)
 */
public class ToDateConversion extends AbstractConversion implements ConversionSupport {
    
    @Override
    public boolean support(@NotNull TypeDescriptor sourceType, @NotNull TypeDescriptor targetType) {
        Class<?> objectType = targetType.getObjectType();
        return ClassUtil.isAssignable(Date.class, objectType);
    }
    
    @Override
    public Object convert(@NotNull Object source, @NotNull TypeDescriptor sourceType, @NotNull TypeDescriptor targetType) {
        if (source instanceof Date) {
            return source;
        }
        
        Class<?> objectType = targetType.getObjectType();
        if (source instanceof TemporalAccessor) {
            return wrap(TemporalUtil.toInstant((TemporalAccessor) source).toEpochMilli(), objectType);
        } else if (source instanceof Calendar) {
            Calendar calendar = (Calendar) source;
            return wrap(calendar.getTime(), objectType);
        } else if (source instanceof Number) {
            return wrap(((Number) source).longValue(), objectType);
        } else {
            // 统一按照字符串处理
            String valueStr = convertToStr(source);
            Date date = DateUtil.parse(valueStr);
            return wrap(date, objectType);
        }
    }
    
    protected Date wrap(Date date, Class<?> targetType) {
        if (Date.class.equals(targetType)) {
            return date;
        } else if (java.sql.Date.class.equals(targetType)) {
            return new java.sql.Date(date.getTime());
        } else if (Time.class.equals(targetType)) {
            return new java.sql.Time(date.getTime());
        } else if (Timestamp.class.equals(targetType)) {
            return new java.sql.Timestamp(date.getTime());
        } else
            throw new UnsupportedOperationException("暂不不支持的时间类型：" + targetType);
    }
    
    protected Date wrap(long mills, Class<?> targetType) {
        if (Date.class.equals(targetType)) {
            return new Date(mills);
        } else if (java.sql.Date.class.equals(targetType)) {
            return new java.sql.Date(mills);
        } else if (Time.class.equals(targetType)) {
            return new java.sql.Time(mills);
        } else if (Timestamp.class.equals(targetType)) {
            return new java.sql.Timestamp(mills);
        } else
            throw new UnsupportedOperationException("暂不不支持的时间类型：" + targetType);
    }
}
